package com.hxzy.controller.back;

import cn.hutool.crypto.digest.BCrypt;
import com.hxzy.common.constants.RedisConstant;
import com.hxzy.common.enums.AckCode;
import com.hxzy.common.exception.WaimaiException;
import com.hxzy.common.util.TokenUtil;
import com.hxzy.common.vo.R;
import com.hxzy.config.WaimaiThreadLocal;
import com.hxzy.dto.back.LoginDTO;
import com.hxzy.entity.Employee;
import com.hxzy.entity.Merchandiser;
import com.hxzy.service.EmployeeService;
import com.hxzy.service.MerchandiserService;
import com.hxzy.vo.back.AdminLoginVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

/**
 * @Author wy
 * @Description 后台登录控制器
 * @Date 2023/4/4 15:56
 * @Version 1.0
 */
@Api(tags = "后端登录API")
@RestController
@RequestMapping(value = "/api")
@Log4j2
public class BackLoginController {


    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 管理员
     */
    @Autowired
    private EmployeeService employeeService;

    /**
     * 商家
     */
    @Autowired
    private MerchandiserService merchandiserService;

    /**
     * 令牌管理工具类
     */
    @Autowired
    private TokenUtil tokenUtil;

    /**
     * 登录  前端axios   axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
     * 1、除了get请求以外，其它的请求默认(put,post,delete)都是以 content-type="application/json"格式提交
     * 前端  application/json 提交，后台必须用 inputStream流来获取数据，不允许使用request.getParameter("键")来获取数据
     * springmvc框架帮我实现 流转换成json对象代码  @RequestBody
     *
     * 2、前端请求  content-type="application/x-www-form-urlencoded"，标准的form表单提交，  jquery.js
     * 只能使用request.getParameter("键") 取值
     * @param loginDTO
     * @return
     */
    @ApiOperation(value = "登录")
    @PostMapping(value = "/login")
    public R login(@RequestBody  @Valid LoginDTO  loginDTO){

        //1、redis中验证，验证码是否过期
        String redisKey= RedisConstant.getRedisKey(RedisConstant.CAPTCHA_KEY,loginDTO.getUuid());
        Object redisValue=this.redisTemplate.opsForValue().get(redisKey);
        if(redisValue==null){
            return R.build(AckCode.SMS_CODE_OVERTIME);
        }
        //2、验证验证码是否正确
        if(!redisValue.toString().equalsIgnoreCase(loginDTO.getCode())){
            return R.build(AckCode.SMS_CODE_WRONG);
        }
        //3、删除redis的验证码
        this.redisTemplate.delete(redisKey);

        //4、查询数据库，根据用户名查询对象
        AdminLoginVO adminLoginVO = this.findByLoginName(loginDTO);

        //5、自定义对象，换取令牌(uuid)-->jwt
        String   jwtToken=tokenUtil.createJwtToken(adminLoginVO);
        return R.okHasData(jwtToken);
    }


    private AdminLoginVO findByLoginName(LoginDTO loginDTO){

        AdminLoginVO adminLoginVO=null;
        String loginPwd="";
        boolean  status=true;
        AckCode  ackCode=null;

        Employee  employee=this.employeeService.login(loginDTO);
        if(employee==null){
            Merchandiser merchandiser=this.merchandiserService.login(loginDTO);
            if(merchandiser!=null){
                adminLoginVO=new AdminLoginVO();
                adminLoginVO.setAccountType(2);
                adminLoginVO.setName(merchandiser.getName());
                adminLoginVO.setAvatar(merchandiser.getPicture());
                adminLoginVO.setId(merchandiser.getId());
                loginPwd=merchandiser.getLoginPwd();
                if(merchandiser.getStatus().intValue()!=0){
                    status=false;
                    ackCode=AckCode.ENTERPRISE_NOT_VALIDATED;
                }
            }
        }else{
            adminLoginVO=new AdminLoginVO();
            adminLoginVO.setAccountType(1);
            adminLoginVO.setName(employee.getLoginName());
            adminLoginVO.setAvatar(employee.getAvatar());
            adminLoginVO.setId(employee.getId());
            loginPwd=employee.getLoginPwd();
            if(employee.getStatus().intValue()==1){
                status=false;
                ackCode=AckCode.DEVICE_BANNED;
            }
        }

        if(adminLoginVO==null){
            log.info(loginDTO.getLoginName()+","+AckCode.USER_NOT_FOUND.getMsg());
            throw new WaimaiException(AckCode.USERNAME_PASSWORD_ERROR);
        }

        //验证密码对不对
        boolean corrent= BCrypt.checkpw(loginDTO.getLoginPwd(), loginPwd);
        if(!corrent){
            log.info(loginDTO.getLoginName()+","+AckCode.USER_PASSWORD_ERROR.getMsg());
            throw new WaimaiException(AckCode.USERNAME_PASSWORD_ERROR);
        }

        //判断状态
        if( !status){
            throw new WaimaiException(ackCode);
        }
        return adminLoginVO;
    }


    /**
     * 获取当前用户信息
     * @return
     */
    @ApiOperation(value = "获取当前用户信息")
    @GetMapping(value = "/user/info")
    public R<AdminLoginVO> userInfo(){
        AdminLoginVO adminLoginVO = WaimaiThreadLocal.adminThreadLocal.get();
        return R.okHasData(adminLoginVO);
    }

    /**
     * 退出登录
     * @return
     */
    @ApiOperation(value = "退出登录")
    @PostMapping(value = "/logout")
    public R logout(){
        this.tokenUtil.backLogout();
        return R.ok();
    }


}
